package office.pdf.easypdf;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.spire.doc.Document;
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfConvertOptions;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.utilities.PdfTable;
import com.spire.pdf.utilities.PdfTableExtractor;
import lombok.extern.slf4j.Slf4j;
import office.word.docx4j.DocumentHeadDO;
import office.word.docx4j.DocumentHeadLevelEnum;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import wiki.xsx.core.pdf.doc.*;
import wiki.xsx.core.pdf.handler.XEasyPdfHandler;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 描述
 * XSL-FO 协议
 * @author: zhanglu
 * @date: 2023/7/24 14:22
 * @modify: 修改人信息, 修改内容 2023/7/24 14:22
 */
@Slf4j
public class PdfOpTest {

    //子标题最大数量
    public static final Integer SUB_HEAD_MAX_COUNT = 100;
    //标题最大数量
    public static final Integer HEAD_MAX_COUNT = 1000;
    //最大页数
    public static final Integer PAGE_MAX_COUNT = 100;


    public static void main(String[] args) throws Exception {
//        // 定义fop配置文件路径
//        String configPath = "E:\\pdf\\template\\fop.xconf";
//        // 定义xsl-fo模板路径
//        String templatePath = "E:\\pdf\\template\\xml\\template.fo";
//        // 定义xml数据路径
//        String xmlPath = "E:\\pdf\\template\\xml\\data.xml";
//        // 定义pdf输出路径
//        String outputPath = "E:\\pdf\\test\\fo\\xml.pdf";
//        // 转换pdf
//        XEasyPdfTemplateHandler.Template.build().setConfigPath(configPath).setDataSource(
//                XEasyPdfTemplateHandler.DataSource.XML.build().setTemplatePath(templatePath).setXmlPath(xmlPath)
//        ).transform(outputPath);
        // 转换pdf
//        XEasyPdfTemplateDocument document = XEasyPdfTemplateHandler.Document.build().addPage(
//                XEasyPdfTemplateHandler.Page.build().addBodyComponent(
//                        XEasyPdfTemplateHandler.Text.build().setText("hello world")
//                )
//        );
//        String content = document.getContent();
//        WordprocessingMLPackage wordprocessingMLPackage = WordprocessingMLPackage.createPackage();
//        wordprocessingMLPackage.save(new FileOutputStream(wordFile), Docx4J.FLAG_EXPORT_PREFER_XSL);

        // 定义pdf输出路径
        String wordFile = "/Users/zhanglu/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/c9a1c762ab6161f8ffce2831a28327a2/Message/MessageTemp/9600bc6c7aa514051e9c3bfe2546162d/File/分包结算协议--王灵剑重庆＋九回弱电(1).docx";
        String pdfFile = "/Users/zhanglu/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/c9a1c762ab6161f8ffce2831a28327a2/Message/MessageTemp/9600bc6c7aa514051e9c3bfe2546162d/File/分包结算协议--王灵剑重庆＋九回弱电(1).pdf";

//        //获取大纲列表
//        getDocumentBookmarks(FileUtil.readBytes(pdfFile));
//        //获取大纲树形列表
//        getDocumentBookmarkTree(FileUtil.readBytes(pdfFile));
//
//        //获取表格数据
//        TableExtractDO table = getTable(FileUtil.readBytes(pdfFile), 63);
//        System.out.println(JSONUtil.toJsonStr(table));
//        FileUtil.writeBytes(generateExcel(table), "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册2.xlsx");

//        //有问题
//        ByteArrayOutputStream[] outs = getTableByPageRange(FileUtil.readBytes(pdfFile), 1, 3);
//        FileUtil.writeBytes(outs[0].toByteArray(), "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册2.docx");

//        //pdf转word (响应时长，(3 + n)秒)
//        byte[] bytes = pdfToWordByPageNo(FileUtil.readBytes(pdfFile), Arrays.asList(1, 2));
//        FileUtil.writeBytes(bytes, "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册2.docx");

        //pdf转word (响应时长，(3 + n)秒)
        byte[] bytes = pdfToWordByPageNo(FileUtil.readBytes(pdfFile), 1, 2);
        FileUtil.writeBytes(bytes, wordFile);

        //pdf小文件转为word
//        FileUtil.writeBytes(smallPdfToWord(FileUtil.readBytes("/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册3/2.pdf")),
//                "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册333.docx");

//        String encode = Base64.encode(FileUtil.readBytes("/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册3/2的副本.docx"));
//        FileUtil.writeUtf8String(encode, "/Users/zhanglu/Desktop/tmp/pdfbox/输变电工程质量检测工作手册3/2的副本.txt");
//        System.out.println(encode);

//        byte[] bytes = extractExcel(FileUtil.readBytes("/Users/zhanglu/Desktop/全区教体系统防灾减灾和安全生产大排查大整治专项行动方案.pdf"), 14);
//        FileUtil.writeBytes(bytes, FileUtil.file("/Users/zhanglu/Desktop/全区教体系统防灾减灾和安全生产大排查大整治专项行动方案14.xlsx"));

    }

    /**
     * 根据表格数据生成excel
     *  - 默认样式
     *  - 不支持合并
     * @param table 表格数据
     * @return      excel格式字节数组
     */
    public static byte[] generateExcel(TableExtractDO table){
        try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            ExcelWriter excelWriter = ExcelUtil.getBigWriter();
            List<List<String>> rows = table.getRowsColumns();
            if(true){
                return new byte[0];
            }
            //设置单元格宽度
            table.getColumnSizeMap().forEach((k, v) -> excelWriter.setColumnWidth(k, (v * 2) > 255 ? 255 : v * 2));
            //垂直居中
            excelWriter.getCellStyle().setVerticalAlignment(VerticalAlignment.CENTER);
            //水平居左
            excelWriter.getCellStyle().setAlignment(HorizontalAlignment.LEFT);
            //自动单元格大小
            excelWriter.autoSizeColumnAll();
            // 一次性写出内容，使用默认样式
            excelWriter.write(rows);
            //输出到字节流
            excelWriter.getWorkbook().write(out);
            //关闭writer，释放内存
            excelWriter.close();
            return out.toByteArray();
        } catch (Exception e) {
            log.error("生成excel异常", e);
            return new byte[0];
        }
    }

    /**
     * pdf小文件转为word
     * @param pdfBytes  pdf格式字节数组
     * @return          docx格式字节数组
     */
    public static byte[] smallPdfToWord(byte[] pdfBytes){
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        try {
            //加载pdf
            XEasyPdfDocument document = XEasyPdfHandler.Document.load(new ByteArrayInputStream(pdfBytes));
            Assert.isTrue(document.getPageList().size() <= 3, "无效的参数，页数超出限制，最大3页");
            //加载单页PDF文档
            PdfDocument pdf = new PdfDocument(pdfBytes);
            //设置字体包路径
            PdfDocument.setCustomFontsFolders("/Users/zhanglu/Downloads/serif");
            //单页pdf转为word
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            pdf.saveToStream(out, FileFormat.DOCX);
            out.close();
            pdf.close();
            return out.toByteArray();
        } catch (Exception e){
            log.error("指定pdf页转word异常", e);
        }
        return new byte[0];
    }

    /**
     * 指定pdf页转word
     *  - 将大的pdf文件拆分成单页的pdf文件
     *  - 根据输入的页号将选中的pdf转成docx
     *  - 将docx合并为一个完整的docx
     * @param pdfBytes  pdf格式字节数组
     * @param pageNos   页号，可连续，可跳跃，若输入相同的页号，则重复提取，最大20个元素
     * @return          docx格式字节数组
     */
    public static byte[] pdfToWordByPageNo(byte[] pdfBytes, List<Integer> pageNos) {
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        String tmpDir = FileUtil.getTmpDirPath() + File.separator + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN);
        try {
            //检查输入
            Assert.isTrue(ObjectUtil.isNotEmpty(pageNos), "请输入需要处理的页号");
            //检查指定页的范围，不能超过最大限制
            Assert.isTrue(pageNos.size() <= PAGE_MAX_COUNT, "无效的参数，页数超出限制，最大{}页", PAGE_MAX_COUNT);
            //加载pdf
            XEasyPdfDocument document = XEasyPdfHandler.Document.load(new ByteArrayInputStream(pdfBytes));
            //检查指定页的范围，不能超过源文件范围
            Assert.isTrue(pageNos.stream().allMatch(o -> o >= 1), "无效的参数，页号必须大于等于1");
            Assert.isTrue(pageNos.stream().allMatch(o -> o <= document.getPageList().size()), "无效的参数，页号超出文档范围");
            //申请临时文件目录
            FileUtil.mkdir(tmpDir);
            //pdf拆分成单页
            document.splitter().split(tmpDir, "");
            //关闭x-esay-pdf流，后续采用spire技术处理
            document.close();
            //指定页面转成word
            List<byte[]> bytes = new ArrayList<>();
            for (int i = 0; i < pageNos.size(); i++) {
                log.info("pdf to word : {}", tmpDir + File.separator + pageNos.get(i) + ".pdf");
                //加载单页PDF文档
                PdfDocument pdf = new PdfDocument(tmpDir + File.separator + pageNos.get(i) + ".pdf");
                //设置字体包路径
                PdfDocument.setCustomFontsFolders("/Users/zhanglu/Downloads/serif");
                //单页pdf转为word
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                pdf.saveToStream(out, FileFormat.DOCX);
                bytes.add(out.toByteArray());
                out.close();
                pdf.close();
            }
            //word合并
            return mergeWords(bytes);
        } catch (Exception e){
            log.error("指定pdf页转word异常", e);
        } finally {
            //删除临时目录
            FileUtil.del(tmpDir);
        }
        return new byte[0];
    }

    /**
     * 指定pdf起止页转word
     *  - 将大的pdf文件拆分成单页的pdf文件
     *  - 根据输入的页号将选中的pdf转成docx
     *  - 将docx合并为一个完整的docx
     * @param pdfBytes  pdf格式字节数组
     * @param startPageNo   起始页号，若输入相同的页号，提取输入页
     * @param endPageNo     起始页号，若输入相同的页号，提取输入页，间隔范围最大20个元素
     * @return          docx格式字节数组
     */
    public static byte[] pdfToWordByPageNo(byte[] pdfBytes, Integer startPageNo, Integer endPageNo) throws Exception {
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        String tmpDir = FileUtil.getTmpDirPath() + File.separator + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN);
        try {
            //检查输入参数
            Assert.isTrue(ObjectUtil.isNotEmpty(startPageNo), "请输入起始页号");
            Assert.isTrue(ObjectUtil.isNotEmpty(startPageNo), "请输入结束页号");
            //检查指定页的范围，不能超过最大限制
            Assert.isTrue((endPageNo - startPageNo) <= PAGE_MAX_COUNT, "无效的参数，页数超出限制，最大{}页", PAGE_MAX_COUNT);
            //加载pdf
            XEasyPdfDocument document = XEasyPdfHandler.Document.load(new ByteArrayInputStream(pdfBytes));
            Assert.isTrue(startPageNo >= 1, "无效的参数，起始页号必须大于等于1");
            Assert.isTrue(endPageNo <= document.getPageList().size(), "无效的参数，结束页号超出文档范围");
            //申请临时文件目录
            FileUtil.mkdir(tmpDir);
            //pdf拆分成单页
            document.splitter().split(tmpDir, "");
            //关闭x-esay-pdf流，后续采用spire技术处理
            document.close();
            List<byte[]> bytes = new ArrayList<>();
            for (int i = (startPageNo - 1); i < endPageNo; i++) {
                log.info("pdf to word : {}", tmpDir + File.separator + (i + 1) + ".pdf");
                //加载单页PDF文档
                PdfDocument pdf = new PdfDocument(tmpDir + File.separator + (i + 1) + ".pdf");
                //设置字体包路径
//                PdfDocument.setCustomFontsFolders("/Users/zhanglu/Downloads/serif");
                //单页pdf转为word
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                pdf.saveToStream(out, FileFormat.DOCX);
                bytes.add(out.toByteArray());
                out.close();
                pdf.close();
            }
            //word合并
            return mergeWords(bytes);
        } catch (Exception e){
            log.error("指定pdf起止页转word异常", e);
        } finally {
            //删除临时目录
            FileUtil.del(tmpDir);
        }
        return new byte[0];
    }

    /**
     * 合并word
     * @param bytes     docx格式字节数组列表
     * @return          合并后的docx格式字节数组
     */
    public static byte[] mergeWords(List<byte[]> bytes) {
        try {
            if(ObjectUtil.isEmpty(bytes)){
                return new byte[0];
            }
            Assert.isTrue(bytes.size() <= PAGE_MAX_COUNT, "无效的参数，页数超出限制，最大{}页", PAGE_MAX_COUNT);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            //创建 Document 类的对象并从磁盘加载 Word 文档
            Document document = new Document();
            for (int i = 0; i < bytes.size(); i++) {
                //子文件合并
                document.insertTextFromStream(new ByteArrayInputStream(bytes.get(i)), com.spire.doc.FileFormat.Docx);
            }
            //输出合并后的word文件
            document.saveToStream(out, com.spire.doc.FileFormat.Docx);
            return out.toByteArray();
        } catch (Exception e) {
            log.error("合并word异常", e);
        }
        return new byte[0];
    }

    public static ByteArrayOutputStream[] getTableByPageRange(byte[] pdfBytes, Integer startPageNo, Integer endPageNo){
        ByteArrayOutputStream[] out = null;
        //加载示例PDF文档
        PdfDocument pdf = new PdfDocument(pdfBytes);
        out = pdf.saveToStream(startPageNo, endPageNo, FileFormat.DOCX);
        pdf.close();
        return out;
    }


    /**
     * 获取pdf表格数据
     *  - 文件任意大小
     *  - 只获取数据
     * @param pdfBytes  pdf格式字节数据
     * @param pageNo    指定页
     * @return          表格数据
     */
    public static TableExtractDO getTable(byte[] pdfBytes, Integer... pageNo) {
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        String tmpDir = FileUtil.getTmpDirPath() + File.separator + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN);
        TableExtractDO tableExtractDO = new TableExtractDO();
        try {
            //加载pdf
            XEasyPdfDocument document = XEasyPdfHandler.Document.load(new ByteArrayInputStream(pdfBytes));
            //申请临时文件目录
            FileUtil.mkdir(tmpDir);
            //pdf拆分成单页
            document.splitter().split(tmpDir, "");
            //关闭x-esay-pdf流，后续采用spire技术处理
            document.close();
            for (Integer no : pageNo) {
                //加载单页PDF文档
                PdfDocument pdf = new PdfDocument(tmpDir + File.separator + no + ".pdf");
                //设置字体包路径
                PdfDocument.setCustomFontsFolders("/Users/zhanglu/Downloads/serif");
                //创建实例
                PdfTableExtractor extractor = new PdfTableExtractor(pdf);
                //提取表格
                PdfTable[] pdfTables = extractor.extractTable(0);
                if(ObjectUtil.isEmpty(pdfTables)){
                    continue;
                }
                for (int j = 0; j < pdfTables.length; j++) {
                    //表格
                    PdfTable table = pdfTables[j];
                    //行数
                    int rowCount = table.getRowCount();
                    //列数
                    int columnCount = table.getColumnCount();
                    //遍历行
                    for (int rowIdx = 0; rowIdx < rowCount; rowIdx++) {
                        //添加行
                        TableExtractDO.Row row = new TableExtractDO.Row(rowIdx);
                        tableExtractDO.addRow(row);
                        //遍历列
                        for (int columnIdx = 0; columnIdx < columnCount; columnIdx++) {
                            //获取表格中的文本内容
                            String text = table.getText(rowIdx, columnIdx);
                            //添加单元格
                            tableExtractDO.addColumn(row, columnIdx, text);
                            //计算列宽
                            tableExtractDO.setColumnSizes(columnIdx, text.length());
                        }
                    }
                }
                pdf.close();
            }
        } catch (Exception e){
            log.error("获取pdf表格数据异常", e);
        } finally {
            //删除临时目录
            FileUtil.del(tmpDir);
        }
        return tableExtractDO;
    }

    /**
     * 提取任意pdf指定单页的表格
     *  - 支持大文件
     *  - 仅支持提取单页的表格
     * @param pdfBytes  pdf格式字节数据
     * @return          excel格式字节数组
     */
    public static byte[] extractExcel(byte[] pdfBytes, Integer pageNo) {
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        String tmpDir = FileUtil.getTmpDirPath() + File.separator + DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN);
        try {
            //加载pdf
            XEasyPdfDocument document = XEasyPdfHandler.Document.load(new ByteArrayInputStream(pdfBytes));
            //申请临时文件目录
            FileUtil.mkdir(tmpDir);
            //pdf拆分成单页
            document.splitter().split(tmpDir, "");
            //关闭x-esay-pdf流，后续采用spire技术处理
            document.close();
            //临时pdf文件
            String tmpPdf = tmpDir + File.separator + pageNo + ".pdf";
            //pdf小文件转为excel表格
            return pdfToExcel(FileUtil.readBytes(tmpPdf));
        } catch (Exception e){
            log.error("获取pdf表格数据异常", e);
        } finally {
            //删除临时目录
            FileUtil.del(tmpDir);
        }
        return new byte[0];
    }

    /**
     * pdf小文件转为excel表格（3页以内，包含三页面）
     * @param pdfBytes  pdf格式字节数据
     * @return          excel格式字节数组
     */
    public static byte[] pdfToExcel(byte[] pdfBytes) {
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            PdfDocument pdf = new PdfDocument();
            //加载pdf
            pdf.loadFromBytes(pdfBytes);
            //pdf转xlsx
            pdf.saveToStream(out, FileFormat.XLSX);
            pdf.close();
            return out.toByteArray();
        } catch (Exception e) {
            log.error("pdf小文件转为excel表格异常", e);
        }
        return new byte[0];
    }

    /**
     * 获取文档书签
     * @param pdfBytes  pdf格式字节数据
     */
    public static DocumentHeadDO getDocumentBookmarkTree(byte[] pdfBytes) throws Exception {
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        //加载pdf
        XEasyPdfDocument document = XEasyPdfHandler.Document.load(new ByteArrayInputStream(pdfBytes));
        //获取大纲
        XEasyPdfDocumentBookmark bookmark = document.bookmark();
        List<PDOutlineItem> bms = bookmark.getBookMark();
        //初始化顶级大纲
        DocumentHeadDO head = new DocumentHeadDO();
        head.setHeadLevel(DocumentHeadLevelEnum.H1);
        head.setChilds(new ArrayList<>());
        //顶级大纲找子集
        for (PDOutlineItem bm : bms) {
            DocumentHeadDO h = new DocumentHeadDO();
            h.setHeadLevel(DocumentHeadLevelEnum.H2);
            h.setText(bm.getTitle());
            head.getChilds().add(h);
            //若无子集则返回
            PDOutlineItem firstChild = bm.getFirstChild();
            if(firstChild == null){
                continue;
            }
            //存在子集，继续往下找
            loopBookmark(DocumentHeadLevelEnum.H3.getIndex(), h, firstChild);
        }
        return head;
    }

    /**
     * 获取文档书签
     * @param root
     */
    public static List<DocumentHeadDO> getDocumentBookmarks(DocumentHeadDO root){
        List<DocumentHeadDO> heads = new ArrayList<>();
        loopChilds(HEAD_MAX_COUNT, heads, root);
        System.out.println(JSONUtil.toJsonStr(heads));
        return heads;
    }

    public static void loopChilds(Integer count, List<DocumentHeadDO> heads, DocumentHeadDO h){
        Assert.isTrue(count >= 0, "提取标题异常，子标题过多:{}", count);
        count--;
        heads.add(h);
        if(ObjectUtil.isEmpty(h.getChilds())){
            return;
        }
        for (DocumentHeadDO child : h.getChilds()) {
            loopChilds(count, heads, child);
        }
        h.setChilds(null);
    }

    /**
     * 获取文档大纲
     * @param pdfBytes  pdf格式字节数组
     */
    public static List<DocumentHeadDO> getDocumentBookmarks(byte[] pdfBytes) throws Exception {
        Assert.isTrue(ObjectUtil.isNotEmpty(pdfBytes), "请输入有效的pdf文件");
        DocumentHeadDO root = getDocumentBookmarkTree(pdfBytes);
        List<DocumentHeadDO> heads = getDocumentBookmarks(root);
        return heads;
    }

    /**
     * 找子集
     * @param index 索引
     * @param root  根节点
     * @param head  当前节点
     */
    public static void loopBookmark(Integer index, DocumentHeadDO root, PDOutlineItem head){
        if(ObjectUtil.isEmpty(root)){
            return;
        }
        //初始化子集
        if(ObjectUtil.isEmpty(root.getChilds())){
            root.setChilds(new ArrayList<>());
        }
        DocumentHeadDO h = new DocumentHeadDO();
        //获取子集等级
        h.setHeadLevel(DocumentHeadLevelEnum.getByIndex(index));
        h.setText(head.getTitle());
        root.getChilds().add(h);
        //获取兄弟节点
        PDOutlineItem nextSibling = head.getNextSibling();
        //找兄弟
        loopNext(SUB_HEAD_MAX_COUNT, index, root, nextSibling);
    }

    /**
     * 找兄弟
     * @param count 递归次数限制
     * @param index 索引
     * @param head  当前节点
     * @param next  兄弟节点
     */
    public static void loopNext(Integer count, Integer index, DocumentHeadDO head, PDOutlineItem next){
        Assert.isTrue(count >= 0, "提取标题异常，子标题过多:{}", count);
        count --;
        if(ObjectUtil.isEmpty(next)){
            return;
        }
        //初始化子集
        if(ObjectUtil.isEmpty(head.getChilds())){
            head.setChilds(new ArrayList<>());
        }
        DocumentHeadDO h = new DocumentHeadDO();
        h.setHeadLevel(DocumentHeadLevelEnum.getByIndex(index));
        h.setText(next.getTitle());
        head.getChilds().add(h);
        //找孩子
        if(ObjectUtil.isNotEmpty(next.getFirstChild())){
            loopNext(count, index + 1, h, next.getFirstChild());
        }
        //找兄弟
        loopNext(count, index, head, next.getNextSibling());
    }

}
